//package xyz.erupt.flow.core.engine.impl;
//
//import lombok.extern.slf4j.Slf4j;
//import lombok.var;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//import xyz.erupt.core.exception.EruptApiErrorTip;
//import xyz.erupt.flow.bean.entity.enums.OaStepStatus;
//import xyz.erupt.flow.bean.entity.enums.OaWorkflowStatus;
//import xyz.erupt.flow.core.engine.EruptWorkFlowEngine;
//import xyz.erupt.flow.core.engine.WorkFlowBuilder;
//import xyz.erupt.flow.repository.OaWorkFlowDefinitionRepository;
//
//import javax.persistence.EntityManager;
//import java.time.LocalDateTime;
//
///**
// * @description: 工作流引擎实现
// * @className: EruptWorkFlowEngineImpl
// * @author: PP
// * @date: 2024/10/20 11:02
// * @Version: 1.0
// */
//@Service
//@Slf4j
//public class EruptWorkFlowEngineImpl implements EruptWorkFlowEngine {
//    @Autowired
//    private OaWorkFlowRepository oaWorkFlowRepository;
//    @Autowired
//    private OaStepRepository oaStepRepository;
//    @Autowired
//    private OaExecutionHistoryRepository oaExecutionHistoryRepository;
//    @Autowired
//    private WorkFlowBuilder workFlowBuilder;
//    @Autowired
//    private OaWorkFlowDefinitionRepository workFlowDefinitionRepository;
//    @Autowired
//    private EntityManager entityManager;
//    /**
//     * @description:启动工作流
//     * @author: PP
//     * @date: 2024/10/19 17:36
//     * @param: [workflowDefinitionId]
//     * @return: void
//     **/
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public void startWorkFlow(Long workflowDefinitionId,String formData){
//        var workflowDefinition = workFlowDefinitionRepository.findById(workflowDefinitionId).orElse(null);
//        if (workflowDefinition == null) {
//            throw new EruptApiErrorTip("流程" + workflowDefinitionId + "不存在");
//        } else if (workflowDefinition.getIsStop()) {
//            throw new EruptApiErrorTip("流程可能已经过期，请刷新后重试");
//        }
//        var workflow_id = workFlowBuilder.build(workflowDefinition,formData);
//        entityManager.flush();//强制刷新
//        entityManager.clear();//清空持久上下文
//        var workflow = oaWorkFlowRepository.findById(workflow_id).orElse(null);
//
//        var startStep = workflow.getSteps().get(workflow.getSteps().size()-1);
//        workflow.setStatus(OaWorkflowStatus.IN_PROGRESS);
//        workflow.setCurrentStep(startStep);//假设第一个步骤为起点
//        executeStep(startStep);
//    }
//
//    /***
//     * @description TODO 执行步骤
//     * @param step
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:19:00
//     */
//    private void executeStep(OaStep step){
//        if (step.getStatus() == OaStepStatus.CANCELLED || step.getStatus() == OaStepStatus.REJECTED){
//            return;//如果步骤被撤销则不执行，驳回则判断策略是否执行
//        }
//        log.info("Executing step: {}", step.getName());
//        step.setStatus(OaStepStatus.EXECUTING);
//        oaStepRepository.save(step);
//        //跳转当前节点
//        var workflow = oaWorkFlowRepository.findById(step.getWorkFlow().getId()).orElse(null);
//        workflow.setCurrentStep(step);
//        oaWorkFlowRepository.save(workflow);
//
//        //记录执行历史
//        saveExecutionHistory(step, OaStepStatus.EXECUTING);
//
//        if(OaStep.NODE_TYPE_CONDITIONS.equals(step.getType())){//条件
//            handleConditionalStep(step);
//        } else if (OaStep.NODE_TYPE_CONCURRENTS.equals(step.getType())) {//并行
//            handleParallelStep(step);
//        }else {
//            //普通任务，顺序执行下一个节点
//            proceedToNextStep(step);
//        }
//
////        step.setStatus(OaStepStatus.COMPLETED);
////        oaStepRepository.save(step);
////        saveExecutionHistory(step,OaStepStatus.COMPLETED);
//    }
//
//    /***
//     * @description TODO 处理条件节点
//     * @param step
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:24:23
//     */
//    private void handleConditionalStep(OaStep step){
//        step.setStatus(OaStepStatus.COMPLETED); //完成当前任务
//        oaStepRepository.save(step);//保存根任务
//        saveExecutionHistory(step,OaStepStatus.COMPLETED);//存入历史
//        //开始下面任务
//        for (OaStep nextStep : step.getNextSteps()) {
//            if(checkCondition(nextStep)){//以下一步骤作为优先级执行
//                nextStep.setFormData(step.getFormData());//将上级数据传入
//                executeStep(nextStep);
//            }
//        }
//    }
//
//    /***
//     * @description TODO 处理并行节点
//     * @param step
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:26:35
//     */
//    private void handleParallelStep(OaStep step){
//        step.setStatus(OaStepStatus.COMPLETED); //完成当前任务
//        oaStepRepository.save(step);//保存根任务
//        saveExecutionHistory(step,OaStepStatus.COMPLETED);//存入历史
//        //开始下面任务
//        step.getNextSteps().forEach(nextStep -> {
//            nextStep.setFormData(step.getFormData());//将上级数据传入
//            new Thread(()->executeStep(nextStep)).start();//并行处理每个分支
//        });
//    }
//
//    /***
//     * @description TODO 继续到下一个节点
//     * @param step
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:28:18
//     */
//    private void proceedToNextStep(OaStep step){
//        //若无下个步骤时，分两种情况；情况1：只有一个发送人，则需要自动完成该任务；情况2：最后一个节点无下面任务了（该任务已被用户完成，不需要进行操作）
//        if (step.getNextSteps()!=null && step.getNextSteps().size()>0) {
//            step.setStatus(OaStepStatus.COMPLETED); //完成当前任务
//            oaStepRepository.save(step);//保存根任务
//            saveExecutionHistory(step,OaStepStatus.COMPLETED);//存入历史
//            //开始下面任务
//            for (OaStep nextStep : step.getNextSteps()) {
//                //将上级数据传入
//                nextStep.setFormData(step.getFormData());
//                executeStep(nextStep);
//            }
//        }else if(OaStep.NODE_TYPE_TASK.equals(step.getType())){//只有根节点情况才自动完成，其他情况用户操作完成
//            //自动完成任务
//            var workflow = oaWorkFlowRepository.findById(step.getWorkFlow().getId()).orElse(null);
//            workflow.setStatus(OaWorkflowStatus.COMPLETED);//完成工作流
//            step.setStatus(OaStepStatus.COMPLETED);//完成根任务
//            oaStepRepository.save(step);//保存根任务
//            saveExecutionHistory(step,OaStepStatus.COMPLETED);//存入历史
//            oaWorkFlowRepository.save(workflow);//保存工作流
//        }
//
//    }
//
//    /***
//     * @description TODO 保存回执历史
//     * @param step
//     * @param status
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:29:03
//     */
//    private void saveExecutionHistory(OaStep step, OaStepStatus status){
//        var history = new OaExecutionHistory();
//        history.setWorkFlow(step.getWorkFlow());
//        history.setStep(step);
//        history.setStatus(status);
//        history.setExecutedAt(LocalDateTime.now());
//        oaExecutionHistoryRepository.save(history);
//    }
//
//    /***
//     * @description TODO 回退到指定步骤
//     * @param workflowId
//     * @param stepId
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:32:35
//     */
//    @Override
//    public void getToStep(Long workflowId, Long stepId){
//        var workflow = oaWorkFlowRepository.findById(workflowId).orElseThrow(()-> new EruptApiErrorTip("回退时-未找到该流程,id:"+workflowId));
//        var targetStep = oaStepRepository.findById(stepId).orElseThrow(()->new EruptApiErrorTip("回退时-未找到该节点,id:"+stepId));
//
//        workflow.setCurrentStep(targetStep);//设置当前步骤为目标步骤
//        oaWorkFlowRepository.save(workflow);
//        executeStep(targetStep);//重新执行该步骤
//    }
//
//    /***
//     * @description TODO 驳回到特定步骤
//     * @param workflowId
//     * @param stepId
//     * @return void
//     * @author PP
//     * @date 2024/10/18 16:38:22
//     */
//    @Override
//    public void rejectToStep(Long workflowId, Long stepId){/******后续更新，目前未实现根据策略跳转的方法**/
//        var workflow = oaWorkFlowRepository.findById(workflowId).orElseThrow(()->new EruptApiErrorTip("驳回时-未找到该流程,id:"+workflowId));
//        var rejectStep = oaStepRepository.findById(stepId).orElseThrow(()->new EruptApiErrorTip("驳回时-未找到该节点,id:"+stepId));
//
//        //更新当前步骤为驳回的步骤
//        rejectStep.setStatus(OaStepStatus.REJECTED);
//        workflow.setCurrentStep(rejectStep);
//        oaWorkFlowRepository.save(workflow);//更新工作流状态
//        oaStepRepository.save(rejectStep);
//        executeStep(rejectStep);//重新执行该步骤
//    }
//
//    /***
//     * @description TODO 撤销工作流
//     * @param workflowId
//     * @return void
//     * @author PP
//     * @date 2024/10/18 17:09:48
//     */
//    @Override
//    public void revokeWorkflow(Long workflowId){
//        var workflow = oaWorkFlowRepository.findById(workflowId).orElseThrow(()->new EruptApiErrorTip("未发现该工作流,id:"+workflowId));
//        workflow.setStatus(OaWorkflowStatus.CANCELLED);//更新工作流状态为撤销
//        oaWorkFlowRepository.save(workflow);//更新工作流状态
//
//        //撤销当前步骤和所有已执行步骤
//        for(OaStep step : workflow.getSteps()){
//            if(step.getStatus() == OaStepStatus.EXECUTING || step.getStatus() == OaStepStatus.COMPLETED){
//                revokeStep(step);
//            }
//        }
//    }
//
//    /***
//     * @description TODO 完成任务
//     * @param workflowId
//     * @param stepId
//     * @return void
//     * @author PP
//     * @date 2024/10/18 18:01:20
//     */
//    @Override
//    public void completeTask(Long workflowId, Long stepId,String formData) {
//        OaWorkFlow workflow = oaWorkFlowRepository.findById(workflowId).orElseThrow(() -> new EruptApiErrorTip("完成-未找到工作流,id:"+workflowId));
//        OaStep stepToComplete = oaStepRepository.findById(stepId).orElseThrow(() -> new EruptApiErrorTip("完成-未找到节点,id:"+stepId));
//
//        stepToComplete.setStatus(OaStepStatus.COMPLETED); // 更新步骤状态为已完成
//        stepToComplete.setFormData(formData);//将更新后的表单数据传入
//        workflow.setCurrentStep(stepToComplete);
//        oaWorkFlowRepository.save(workflow); // 更新工作流状态
//        oaStepRepository.save(stepToComplete); // 更新步骤状态
//        saveExecutionHistory(stepToComplete,OaStepStatus.COMPLETED);
//        proceedToNextStep(stepToComplete); // 执行后续步骤
//    }
//
//    /***
//     * @description TODO 撤销步骤
//     * @param step
//     * @return void
//     * @author PP
//     * @date 2024/10/18 17:11:48
//     */
//    private void revokeStep(OaStep step){
//        step.setStatus(OaStepStatus.CANCELLED);//更新步骤状态为撤销
//        oaStepRepository.save(step);
//
//        //递归撤销所有后续步骤
//        for(OaStep nextStep : step.getNextSteps()){
//            revokeStep(nextStep);
//        }
//    }
//
//    /***
//     * @description TODO 判断条件
//     * @param step
//     * @return boolean
//     * @author PP
//     * @date 2024/10/18 16:43:08
//     */
//    private boolean checkCondition(OaStep step){
//        return true;//实现条件逻辑
//    }
//}
